package com.hw.atomic;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerArray;
import java.util.concurrent.atomic.AtomicReference;


/**
 * @author hewei8<br>
 * Date 2019年1月29日<br>
 * <p>原子操作可以保证线程对数据的操作的正确性</p>
 */
public class AtomicDemo {
	
	public static void main(String[] args) throws InterruptedException {
		AtomicInteger a=new AtomicInteger(10);
		System.out.println(a.getAndAdd(10)+"-"+a.get()+"-"+a.getAndDecrement()+"-"+a.get());
		
		
		System.out.println("-------------------------------------------------------------------");
		
		/*基本数据类型*/
		AtomicInteger ai=new AtomicInteger();
		System.out.println(ai.getAndIncrement());
		
		/*数组类型*/
		int[] nums={0,1,2,3,4};
		AtomicIntegerArray aArray=new AtomicIntegerArray(nums);
		
		/*引用类型*/
		AtomicReference<Person> ar=new AtomicReference<Person>();
		Person person=new Person("hw", 10);
		ar.set(person);
		System.out.println(person);
		
		ExecutorService threadPool=Executors.newCachedThreadPool();
		System.out.println(Arrays.toString(nums));
		threadPool.execute(new AtomicTask("atomic1",ai));
		threadPool.execute(new AtomicTask("atomic2",ai));
		threadPool.execute(new AtomicTask("atomic3",ai));
		
		threadPool.execute(new AtomicArrayTask("aArray1",aArray));
		threadPool.execute(new AtomicArrayTask("aArray2",aArray));
//		threadPool.execute(new AtomicArrayTask("aArray3",aArray));
		
		threadPool.execute(new AtomicRefTask(ar,new Person("hewei", 18)));
		threadPool.execute(new AtomicRefTask(ar,new Person("yp", 16)));
		System.out.println(person);
		
//		Thread.sleep(10000);
		
	}

}

class AtomicTask implements Runnable{
	private AtomicInteger aInteger;
	private SimpleDateFormat sdf=new SimpleDateFormat("hh:MM:ss");
	private String name;
	public AtomicTask(String name,AtomicInteger ai) {
		this.name=name;
		aInteger=ai;
	}
	@Override
	public void run() {
		for(int i=0;i<5;i++) {
			System.out.println("["+sdf.format(new Date())+"] "+this.name+":"+aInteger.getAndIncrement());
		}
	}
}

class AtomicArrayTask implements Runnable {
	
	private AtomicIntegerArray aArray;
	private SimpleDateFormat sdf=new SimpleDateFormat("hh:MM:ss");
	private String name;
	
	public AtomicArrayTask(String name,AtomicIntegerArray aArray) {
		this.name=name;
		this.aArray = aArray;
	}
	
	@Override
	public void run() {
		for(int i=0;i<5;i++) {
			aArray.set(i, i+1);
			System.out.println("["+sdf.format(new Date())+"] "+this.name+" : "+aArray.get(i));
		}
	}

}

class AtomicRefTask implements Runnable {
	private SimpleDateFormat sdf=new SimpleDateFormat("hh:MM:ss");
	private AtomicReference<Person> aPerson;
	private Person person;

	public AtomicRefTask(AtomicReference<Person> aPerson, Person person) {
		this.aPerson = aPerson;
		this.person = person;
	}

	@Override
	public void run() {
//		aPerson.set(person);
		Person p=aPerson.get();
		aPerson.compareAndSet(p, person);
		System.out.println("["+sdf.format(new Date())+"] "+aPerson.get());
		
	}
}

class Person{
	private String name;
	private int age;
	
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
}